home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / XDME / Src / cursor.c < prev    next >
C/C++ Source or Header  |  1996-09-26  |  24KB  |  1,395 lines

  1. /******************************************************************************
  2.  
  3.     MODUL
  4.     $Id: cursor.c 1.1 1994/08/09 15:55:36 digulla Exp digulla $
  5.  
  6.     DESCRIPTION
  7.     All routines that only move the cursor.
  8.  
  9.     NOTES
  10.  
  11.     BUGS
  12.  
  13.     TODO
  14.  
  15.     EXAMPLES
  16.  
  17.     SEE ALSO
  18.  
  19.     INDEX
  20.  
  21.     HISTORY
  22.     04. Oct 1992    ada created
  23.     $Log: cursor.c $
  24.  * Revision 1.1  1994/08/09  15:55:36  digulla
  25.  * Initial revision
  26.  *
  27.  
  28. ******************************************************************************/
  29.  
  30. /**************************************
  31.         Includes
  32. **************************************/
  33. #include <defs.h>
  34.  
  35.  
  36. /**************************************
  37.         Globale Variable
  38. **************************************/
  39. Prototype void do_up              (void);
  40. Prototype void do_scrolldown          (void);
  41. Prototype void do_scrollup          (void);
  42. Prototype void do_down              (void);
  43. Prototype void do_page              (void);
  44. Prototype void do_downadd          (void);
  45. Prototype void do_left              (void);
  46. Prototype void do_right           (void);
  47. Prototype void do_tab              (void);
  48. Prototype void do_backtab          (void);
  49. Prototype void do_top              (void);
  50. Prototype void do_bottom          (void);
  51. Prototype void do_firstcolumn          (void);
  52. Prototype void do_firstnb          (void);
  53. Prototype void do_lastcolumn          (void);
  54. Prototype void do_goto              (void);
  55. Prototype void do_screentop          (void);
  56. Prototype void do_screenbottom          (void);
  57. Prototype void do_wleft           (void);
  58. Prototype void do_wright          (void);
  59. Prototype void do_col              (void);
  60. Prototype void do_scroll          (int);
  61. Prototype void do_match           (void);
  62. Prototype void do_ping              (void);
  63. Prototype void do_pong              (void);
  64. Prototype void do_undo              (void);
  65. Prototype int  get_pong           (int);
  66. Prototype void escapecomlinemode      (void);
  67. Prototype void do_esc              (void);
  68. Prototype void do_recall          (void);
  69. Prototype void markerkill          (ED *);
  70.  
  71. Prototype char    * HistoBuff[];
  72. Prototype WORD      NumHistoLines;
  73. Prototype WORD      HistoLine;
  74.  
  75.  
  76. /**************************************
  77.       Interne Defines & Strukturen
  78. **************************************/
  79.  
  80.  
  81. /**************************************
  82.         Interne Variable
  83. **************************************/
  84. static struct TextMarker marker[PINGDEPTH];
  85.  
  86. /* TODO: replace define by function for infinite history */
  87.  
  88. #define MaxHistoLines        40
  89.  
  90. /* HistoBuff is filled [0..NumHistoLines-1], NumHistoLines is in
  91.    [0..MaxHistoLines], HistoLine is in [0..NumHistoLines]. If NumHistoLines
  92.    is 0, then the HistoryBuffer is empty. */
  93.  
  94. char * HistoBuff[MaxHistoLines];
  95. WORD   NumHistoLines;
  96. WORD   HistoLine;
  97.  
  98.  
  99. /**************************************
  100.        Interne Prototypes
  101. **************************************/
  102.  
  103.  
  104.  
  105. void do_up (void)
  106. {
  107.     ED * ep = Ep;
  108.  
  109.     if (!globalflags.Comlinemode)
  110.     {
  111.     if (ep->line)
  112.     {
  113.         text_sync ();
  114.         ep->line --;
  115.         text_load ();
  116.  
  117.         if (Ep->line < Ep->topline)
  118.         {
  119.         ep->topline --;
  120.  
  121.         scroll_display (0, -1, ep->topcolumn, ep->topline,
  122.             ep->topcolumn + Columns, ep->topline + Lines);
  123.         }
  124.     } else
  125.     {
  126.         globalflags.Abortcommand = 1;
  127.     }
  128.     } else
  129.     {
  130.     if (HistoLine)
  131.     {
  132.         HistoLine --;
  133.  
  134.         strcpy (Current, HistoBuff[HistoLine]);
  135.  
  136.         ep->column = Clen = strlen (Current);
  137.         ep->topcolumn = ep->column - Columns + 1;
  138.  
  139.         if (ep->topcolumn < 0)
  140.         ep->topcolumn = 0;
  141.  
  142.         text_redisplaycurrline ();
  143.     }
  144.     }
  145. } /* do_up */
  146.  
  147.  
  148. void do_scrolldown (void)
  149. {
  150.     ED * ep = Ep;
  151.  
  152.     if (ep->topline + Lines < ep->lines)
  153.     {
  154.     text_sync ();
  155.  
  156.     ep->topline ++;
  157.     ep->line ++;
  158.  
  159.     text_load ();
  160.  
  161.     scroll_display (0, 1, ep->topcolumn, ep->topline,
  162.             ep->topcolumn + Columns - 1, ep->topline + Lines - 1);
  163.     } else
  164.     globalflags.Abortcommand = 1;
  165. } /* do_scrolldown */
  166.  
  167.  
  168. void do_scrollup (void)
  169. {
  170.     ED * ep = Ep;
  171.  
  172.     if (ep->topline)
  173.     {
  174.     text_sync ();
  175.  
  176.     ep->topline --;
  177.     ep->line --;
  178.  
  179.     text_load ();
  180.  
  181.     scroll_display (0, -1, ep->topcolumn, ep->topline,
  182.             ep->topcolumn + Columns - 1, ep->topline + Lines - 1);
  183.     } else
  184.     globalflags.Abortcommand = 1;
  185. } /* do_scrollup */
  186.  
  187.  
  188. void do_down (void)
  189. {
  190.     ED * ep = Ep;
  191.  
  192.     if (!globalflags.Comlinemode)
  193.     {
  194.     if (ep->line + 1 < ep->lines)
  195.     {
  196.         text_sync ();
  197.  
  198.         ep->line ++;
  199.  
  200.         text_load ();
  201.  
  202.         if (ep->line - ep->topline >= Lines)
  203.         {
  204.         ep->topline ++;
  205.  
  206.         scroll_display (0, 1, ep->topcolumn, ep->topline,
  207.                 ep->topcolumn + Columns, ep->topline + Lines);
  208.         }
  209.     } else
  210.         globalflags.Abortcommand = 1;
  211.     } else
  212.     { /* Comlinemode */
  213.     if (HistoLine < NumHistoLines)
  214.     {
  215.         HistoLine ++;
  216.  
  217.         if (HistoLine != NumHistoLines)
  218.         strcpy (Current, HistoBuff[HistoLine]);
  219.         else
  220.         *Current = 0;
  221.  
  222.         ep->column = Clen = strlen (Current);
  223.         ep->topcolumn = ep->column - Columns + 1;
  224.  
  225.         if (ep->topcolumn < 0)
  226.         ep->topcolumn = 0;
  227.  
  228.         text_redisplaycurrline ();
  229.     }
  230.     } /* if (!Comlinemode) */
  231. } /* do_down */
  232.  
  233.  
  234. /*
  235.     PAGEUP
  236.     PAGEDOWN
  237.     PAGELEFT
  238.     PAGERIGHT
  239.     PAGESET n    (n = 0 to 100 for percentage of #rows to scroll, minimum 1)
  240.         can be > 100.
  241. */
  242.  
  243. void do_page (void)
  244. {
  245.     ED     * ep = Ep;
  246.     UWORD n,
  247.        t;
  248.  
  249.     switch(av[0][4])
  250.     {
  251.     case 'u':
  252.         if (!ep->topline && !ep->line) return;
  253.  
  254.         text_sync ();
  255.  
  256.         if (ep->line != ep->topline)
  257.         {
  258.         ep->line = ep->topline;
  259.  
  260.         text_load ();
  261.         return;
  262.         }
  263.  
  264.         n = Lines * PageJump / 100;
  265.  
  266.         if (ep->topline < n)
  267.         n = ep->topline;
  268.  
  269.         ep->line -= n;
  270.         ep->topline -= n;
  271.  
  272.         text_load ();
  273.  
  274.         if (!Nsu)
  275.         scroll_display (0, -n, 0, ep->topline, MAXLINELEN,
  276.             ep->topline + Lines);
  277.         break;
  278.  
  279.     case 'd':
  280.         if (ep->topline + Lines >= ep->lines &&
  281.             ep->line == ep->lines -1)
  282.         return;
  283.  
  284.         text_sync ();
  285.  
  286.         if (ep->line != ep->topline + Lines -1)
  287.         {
  288.         ep->line = ep->topline + Lines -1;
  289.  
  290.         if (ep->line >= ep->lines)
  291.             ep->line = ep->lines -1;
  292.  
  293.         text_load ();
  294.         return;
  295.         }
  296.  
  297.         n = Lines * PageJump / 100;
  298.  
  299.         ep->line    += n;
  300.         ep->topline += n;
  301.  
  302.         if (ep->line >= ep->lines)
  303.         ep->line = ep->lines - 1;
  304.  
  305.         text_load ();
  306.  
  307.         if (!Nsu)
  308.         scroll_display (0, n, 0, ep->topline, MAXLINELEN,
  309.             ep->topline + Lines);
  310.         break;
  311.  
  312.     case 'l':
  313.         if (!ep->topcolumn && !ep->column) return;
  314.  
  315.         t = firstns (Current);
  316.  
  317.         if (ep->column != ep->topcolumn)
  318.         {
  319.         if (t > ep->topcolumn && ep->column != t)
  320.             ep->column = t;
  321.         else
  322.             ep->column = ep->topcolumn;
  323.  
  324.         text_sync ();
  325.         return;
  326.         }
  327.  
  328.         n = Columns * PageJump / 100;
  329.  
  330.         if (ep->topcolumn < n)
  331.         n = ep->topcolumn;
  332.  
  333.         if (t < ep->column && t > ep->column - n)
  334.         ep->column = t;
  335.         else
  336.         ep->column -= n;
  337.         ep->topcolumn -= n;
  338.  
  339.         text_sync ();
  340.  
  341.         if (!Nsu)
  342.         scroll_display (-n, 0, 0, ep->topline, MAXLINELEN,
  343.             ep->topline + Lines);
  344.         break;
  345.  
  346.     case 'r':
  347.         if (ep->topcolumn + Columns >= MAXLINELEN &&
  348.             ep->column == MAXLINELEN-1)
  349.         return;
  350.  
  351.         text_sync ();
  352.  
  353.         t = LINELEN(ep,ep->line);
  354.  
  355.         if (ep->column != ep->topcolumn + Columns -1)
  356.         {
  357.         if (t < ep->topcolumn + Columns && t != ep->column)
  358.             ep->column = t;
  359.         else
  360.             ep->column = ep->topcolumn + Columns -1;
  361.  
  362.         if (ep->column >= MAXLINELEN)
  363.             ep->column = MAXLINELEN - 1;
  364.  
  365.         text_sync ();
  366.         return;
  367.         }
  368.  
  369.         n = Columns * PageJump / 100;
  370.  
  371.         if (t > ep->column && t < ep->column + n)
  372.         ep->column = t;
  373.         else
  374.         ep->column    += n;
  375.         ep->topcolumn += n;
  376.  
  377.         if (ep->column >= MAXLINELEN)
  378.         ep->column = MAXLINELEN - 1;
  379.  
  380.         text_sync ();
  381.  
  382.         if (!Nsu)
  383.         scroll_display (n, 0, 0, ep->topline, MAXLINELEN,
  384.             ep->topline + Lines);
  385.         break;
  386.  
  387.     case 's':
  388.         PageJump = atoi ((char *)av[1]);
  389.  
  390.         if (PageJump > 100)
  391.         PageJump = 100;
  392.         else if (PageJump < 1)
  393.         PageJump = 1;
  394.  
  395.         break;
  396.     }
  397. } /* do_page */
  398.  
  399.  
  400. void do_downadd (void)
  401. {
  402.     ED      * ep = Ep;
  403.     UBYTE * ptr;
  404.  
  405.     if (ep->line + 1 == ep->lines)
  406.     {
  407.     ep->modified = 1;
  408.  
  409.     if (makeroom (32))
  410.     {
  411.         ptr = allocline (1);
  412.  
  413.         SETLINE(ep,ep->lines,ptr);
  414.         ep->lines ++;
  415.     } else
  416.     {
  417.         nomemory ();
  418.     }
  419.     }
  420.  
  421.     do_down ();
  422. } /* do_downadd */
  423.  
  424.  
  425. void do_left (void)
  426. {
  427.     ED * ep = Ep;
  428.  
  429.     if (ep->column)
  430.     {
  431.     ep->column --;
  432.  
  433.     if (ep->column < ep->topcolumn)
  434.         text_adjust (FALSE);
  435.     } else
  436.     globalflags.Abortcommand = 1;
  437. } /* do_left */
  438.  
  439.  
  440. void do_right (void)
  441. {
  442.     ED * ep = Ep;
  443.  
  444.     if (ep->column != 254)
  445.     {
  446.     if (Current[ep->column] == 0)
  447.     {
  448.         Current[ep->column] = ' ';
  449.         Current[ep->column+1]= '\0';
  450.  
  451.         Clen ++;
  452.     }
  453.  
  454.     ep->column ++;
  455.  
  456.     if (ep->column - ep->topcolumn >= Columns)
  457.         text_adjust (FALSE);
  458.     } else
  459.     globalflags.Abortcommand = 1;
  460. } /* do_right */
  461.  
  462.  
  463. void do_tab (void)
  464. {
  465.     WORD  n;
  466.     ED    * ep = Ep;
  467.  
  468.     /* TODO */
  469.     for (n=ep->config.tabstop-(ep->column % ep->config.tabstop); n>0; n--)
  470.     do_right ();
  471. } /* do_tab */
  472.  
  473.  
  474. void do_backtab (void)
  475. {
  476.     WORD  n;
  477.     ED    * ep = Ep;
  478.  
  479.     n = ep->column % ep->config.tabstop;
  480.     if (!n)
  481.     n = ep->config.tabstop;
  482.  
  483.     /* TODO */
  484.     for (; n > 0; --n)
  485.     do_left ();
  486. } /* do_backtab */
  487.  
  488.  
  489. void do_top (void)
  490. {
  491.     text_sync ();
  492.  
  493.     Ep->line = 0;
  494.  
  495.     text_load ();
  496.     text_adjust (FALSE);
  497. } /* do_top */
  498.  
  499.  
  500. void do_bottom (void)
  501. {
  502.     text_sync ();
  503.  
  504.     Ep->line = Ep->lines - 1;
  505.  
  506.     text_load ();
  507.     text_adjust (FALSE);
  508. } /* do_bottom */
  509.  
  510.  
  511. void do_firstcolumn (void)
  512. {
  513.     if (Ep->column)
  514.     {
  515.     Ep->column = 0;
  516.     text_adjust (FALSE);
  517.     }
  518. } /* do_firstcolumn */
  519.  
  520.  
  521. void do_firstnb (void)
  522. {
  523.     for (Ep->column = 0; Current[Ep->column] == ' '; Ep->column ++);
  524.  
  525.     if (Current[Ep->column] == 0)
  526.     Ep->column = 0;
  527.  
  528.     text_adjust (FALSE);
  529. } /* do_firstnb */
  530.  
  531.  
  532. void do_lastcolumn (void)
  533. {
  534.     WORD  i;
  535.  
  536.     text_sync ();
  537.  
  538.     i = (globalflags.Comlinemode) ? Clen : LINELEN(Ep,Ep->line);
  539.  
  540.     if (i != Ep->column)
  541.     {
  542.     Ep->column = i;
  543.     text_adjust (FALSE);
  544.     }
  545. } /* do_lastcolumn */
  546.  
  547.  
  548. /*
  549.  * GOTO [+/-]N
  550.  * GOTO BLOCK    start of block
  551.  * GOTO START    start of block
  552.  * GOTO END    end of block
  553.  */
  554.  
  555. void do_goto (void)
  556. {
  557.     Line   line;
  558.     Column col;
  559.     long   i;
  560.     char * ptr = (char *)av[1];
  561.  
  562.     i     = 0;
  563.     line = -1;
  564.     col  = -1;
  565.  
  566.     switch (*ptr)
  567.     {
  568.     case 'b':
  569.     case 's':
  570.        if (ActualBlock.type != BT_NONE && Ep == ActualBlock.ep)
  571.        {
  572.            line = ActualBlock.start_line;
  573.  
  574.            if (ActualBlock.type != BT_LINE)
  575.            col = ActualBlock.start_column;
  576.        }
  577.     break;
  578.  
  579.     case 'e':
  580.         if (ActualBlock.type != BT_NONE && Ep == ActualBlock.ep)
  581.         {
  582.         line = ActualBlock.end_line;
  583.  
  584.         if (ActualBlock.type != BT_LINE)
  585.             col = ActualBlock.end_column;
  586.         }
  587.     break;
  588.  
  589.     case '+':
  590.         i = 1;
  591.  
  592.     case '-':
  593.         line = Ep->line;
  594.  
  595.     default:
  596.         line += atoi(ptr+i);
  597.     } /* switch (*ptr) */
  598.  
  599.     if (line >= Ep->lines)
  600.     line = Ep->lines - 1;
  601.  
  602.     if (line < 0)
  603.     line = 0;
  604.  
  605.     text_sync ();
  606.  
  607.     Ep->line = line;
  608.     if (col != -1)
  609.     Ep->column = col;
  610.  
  611.     text_load ();
  612.     text_adjust (FALSE);
  613. } /* do_goto */
  614.  
  615.  
  616. void do_screentop (void)
  617. {
  618.     text_sync ();
  619.  
  620.     Ep->line = Ep->topline;
  621.  
  622.     text_load ();
  623.     text_adjust (FALSE);
  624. } /* do_screentop */
  625.  
  626.  
  627. void do_screenbottom (void)
  628. {
  629.     text_sync ();
  630.  
  631.     Ep->line = Ep->topline + Lines - 1;
  632.  
  633.     if (Ep->line < 0 || Ep->line >= Ep->lines)
  634.     Ep->line = Ep->lines - 1;
  635.  
  636.     text_load ();
  637.     text_adjust (FALSE);
  638. } /* do_screenbottom */
  639.  
  640.  
  641. void do_wleft ()
  642. {
  643.     ED * ep = Ep;
  644.     int  i;
  645.  
  646.     for (;;)
  647.     {
  648.     i = ep->column;
  649.  
  650.     if (i == 0)
  651.         goto prevline;
  652.  
  653.     i --;
  654.  
  655.     while (i && Current[i] == ' ')
  656.         i --;
  657.  
  658.     if (i == 0 && Current[0] == ' ')
  659.     {
  660. prevline:
  661.         if (globalflags.Comlinemode || ep->line == 0)
  662.         {
  663.         i = ep->column;
  664.         break;
  665.         }
  666.  
  667.         text_sync ();
  668.  
  669.         ep->line --;
  670.  
  671.         text_load ();
  672.  
  673.         ep->column = Clen;
  674.         continue;
  675.     } /* while !SOL && isspace(Current[i]) */
  676.  
  677.     while (i && Current[i] != ' ')
  678.         i --;
  679.  
  680.     if (Current[i] == ' ')
  681.         i ++;
  682.  
  683.     break;
  684.     } /* forever */
  685.  
  686.     ep->column = i;
  687.  
  688.     text_adjust (FALSE);
  689. } /* do_wleft */
  690.  
  691.  
  692. void do_wright()
  693. {
  694.     ED * ep = Ep;
  695.     int  i;
  696.  
  697.     for (;;)
  698.     {
  699.     i = ep->column;
  700.  
  701.     if (i == Clen)
  702.         goto nextline;
  703.  
  704.     while (i != Clen && Current[i] != ' ')  /* skip past current word */
  705.         i ++;
  706.  
  707.     while (i != Clen && Current[i] == ' ')  /* to beg. of next word   */
  708.         i ++;
  709.  
  710.     if (i == Clen)
  711.     {
  712. nextline:
  713.         if (globalflags.Comlinemode || ep->line == ep->lines - 1)
  714.         {
  715.         i = ep->column;
  716.         break;
  717.         }
  718.  
  719.         text_sync ();
  720.  
  721.         ep->line ++;
  722.  
  723.         text_load ();
  724.  
  725.         ep->column = i = 0;
  726.  
  727.         if (Current[0] != ' ')
  728.         break;
  729.  
  730.         continue;
  731.     }
  732.  
  733.     break;
  734.     } /* forever */
  735.  
  736.     ep->column = i;
  737.  
  738.     text_adjust (FALSE);
  739. } /* do_wright() */
  740.  
  741.  
  742. void do_col (void)
  743. {
  744.     int    col;
  745.     char * ptr = (char *)av[1];
  746.  
  747.     switch(*ptr)
  748.     {
  749.     case '+':
  750.         col = text_colno() + atoi(ptr + 1);
  751.         if (col > 254)
  752.         col = 254;
  753.     break;
  754.  
  755.     case '-':
  756.         col = text_colno() + atoi(ptr);
  757.         if (col < 0)
  758.         col = 0;
  759.     break;
  760.  
  761.     default:
  762.         col = atoi(ptr) - 1;
  763.     break;
  764.     }
  765.  
  766.     if (col > 254 || col < 0)
  767.     {
  768.     globalflags.Abortcommand = 1;
  769.     return;
  770.     }
  771.  
  772.     while (Clen < col)
  773.     Current[Clen ++] = ' ';
  774.  
  775.     Current[Clen] = 0;
  776.  
  777.     Ep->column = col;
  778.  
  779.     text_adjust (FALSE);
  780. } /* do_col */
  781.  
  782.  
  783. void do_scroll (int dir) /* SCROLLLEFT SCROLLRIGHT */
  784. {
  785.     ED     * ep = Ep;
  786.     UWORD step      = 4;
  787.  
  788.     if (Nsu)
  789.     return;
  790.  
  791.     if (dir == -1)
  792.     if (av[0][6] == 'l')
  793.         dir = SCROLL_LEFT;
  794.     else
  795.         dir = SCROLL_RIGHT;
  796.  
  797.     if (dir == SCROLL_LEFT)
  798.     {
  799.     if (!ep->topcolumn)
  800.     {
  801.         globalflags.Abortcommand = 1;
  802.         return;
  803.     }
  804.  
  805.     if (ep->topcolumn < step)
  806.         step = ep->topcolumn;
  807.     } else if (dir == SCROLL_RIGHT)
  808.     {
  809.     if ((ep->topcolumn + Columns) >= MAXLINELEN)
  810.     {
  811.         globalflags.Abortcommand = 1;
  812.         return;
  813.     }
  814.  
  815.     if ((ep->topcolumn + Columns + step) >= MAXLINELEN)
  816.         step = MAXLINELEN - (ep->topcolumn + Columns);
  817.     }
  818.  
  819.     if (dir == SCROLL_LEFT)
  820.     {
  821.     ep->topcolumn -= step;
  822.     ep->column    -= step;
  823.     } else
  824.     {
  825.     UWORD end;
  826.  
  827.     /* fill Current with spaces */
  828.     end = ep->column + step;
  829.  
  830.     for ( ; Clen<end; Clen++)
  831.         Current[Clen] = ' ';
  832.  
  833.     Current[Clen] = 0;
  834.  
  835.     ep->topcolumn += step;
  836.     ep->column    += step;
  837.     }
  838.  
  839.     scroll_display ((dir == SCROLL_LEFT ? -step : step), 0,
  840.         ep->topcolumn, ep->topline,
  841.         ep->topcolumn + Columns, ep->topline + Lines);
  842. } /* do_scroll */
  843.  
  844.  
  845. struct pos
  846. {
  847.     UBYTE * ptr;
  848.     ULONG   len;
  849.     Line    lin;
  850.     Column  col;
  851. };
  852.  
  853.  
  854. Prototype int get_char (ED * ep, struct pos * curr, int dir);
  855.  
  856. int get_char (ED * ep, struct pos * curr, int dir)
  857. {
  858.     int c;
  859.  
  860.     if (dir == 0)
  861.     {
  862.     curr->ptr = CONTENTS(Current);
  863.     curr->len = strlen (curr->ptr);
  864.     curr->lin = Ep->line;
  865.     curr->col = Ep->column;
  866.  
  867.     if (curr->col > curr->len)
  868.         curr->col = curr->len - 1;
  869.  
  870.     c = curr->ptr[curr->col];
  871.     }
  872.     else if (dir < 0)
  873.     {
  874.     if (curr->col < 0)
  875.     {
  876.         do
  877.         {
  878.         curr->lin --;
  879.  
  880.         if (curr->lin < 0)
  881.             return (-1);
  882.  
  883.         curr->ptr = GETTEXT(ep,curr->lin);
  884.         curr->len = strlen (curr->ptr);
  885.         } while (!curr->len);
  886.  
  887.         curr->col = curr->len-1;
  888.     } /* col out of range */
  889.  
  890.     c = curr->ptr[curr->col];
  891.  
  892.     curr->col --;
  893.     }
  894.     else
  895.     {
  896.     if (curr->col > curr->len)
  897.     {
  898.         do
  899.         {
  900.         curr->lin ++;
  901.  
  902.         if (curr->lin >= ep->lines)
  903.             return (-1);
  904.  
  905.         curr->ptr = GETTEXT(ep,curr->lin);
  906.         curr->len = strlen (curr->ptr);
  907.         } while (!curr->len);
  908.  
  909.         curr->col = 0;
  910.     } /* col out of range */
  911.  
  912.     c = curr->ptr[curr->col];
  913.  
  914.     curr->col ++;
  915.     }
  916.  
  917.     return (c);
  918. }
  919.  
  920. void do_match (void)
  921. {
  922.     char   dec,     /* char that indicates a "level_down"   */
  923.        inc;     /*        -""-         "level_up"     */
  924.     WORD   dir;     /* direction of search            */
  925.     WORD   level;    /* "level"                              */
  926.     int    c;
  927.     struct pos curr;    /* current position */
  928.  
  929.     /* set start values */
  930.     inc = get_char (Ep, &curr, 0);
  931.  
  932.     /* Check for a known paren and select the search-direction accordingly. */
  933.     switch (inc)
  934.     {
  935.     case '{':
  936.         dir = 1;
  937.         dec = '}';
  938.     break;
  939.  
  940.     case '}':
  941.         dir = -1;
  942.         dec = '{';
  943.     break;
  944.  
  945.     case '[':
  946.         dir = 1;
  947.         dec = ']';
  948.     break;
  949.  
  950.     case ']':
  951.         dir = -1;
  952.         dec = '[';
  953.     break;
  954.  
  955.     case '(':
  956.         dir = 1;
  957.         dec = ')';
  958.     break;
  959.  
  960.     case ')':
  961.         dir = -1;
  962.         dec = '(';
  963.     break;
  964.  
  965.     case '`':
  966.         dir = 1;
  967.         dec = '\'';
  968.     break;
  969.  
  970.     case '\'':
  971.         dir = -1;
  972.         dec = '`';
  973.     break;
  974.  
  975.     case '*':
  976.     case '/': {
  977.         int ln, nested;
  978.  
  979.         {
  980.         int pre, next;
  981.  
  982.         pre = next = 0;
  983.  
  984.         if (curr.col)
  985.             pre = curr.ptr[curr.col-1];
  986.  
  987.         if (curr.col != curr.len-1)
  988.             next = curr.ptr[curr.col+1];
  989.  
  990.         if (inc == '*')
  991.         {
  992.             if (pre == '/')
  993.             {
  994.             if (next == '/')
  995.             {
  996.                 warn ("match: ambigous comment");
  997.                 return;
  998.             }
  999.             else
  1000.                 dir = 1;    /* / * x */
  1001.             }
  1002.             else
  1003.             {
  1004.             if (next == '/')
  1005.                 dir = -1;    /* x * / */
  1006.             else
  1007.                 return;    /* x * x */
  1008.             }
  1009.  
  1010.             /* skip '*' */
  1011.             /* c = dead assign */ get_char (Ep, &curr, dir);
  1012.         }
  1013.         else /* inc == '/' */
  1014.         {
  1015.             if (pre == '*')
  1016.             {
  1017.             if (next == '*')
  1018.             {
  1019.                 warn ("match: ambigous comment");
  1020.                 return;
  1021.             }
  1022.             else
  1023.                 dir = -1;    /* * / x */
  1024.             }
  1025.             else
  1026.             {
  1027.             if (next == '*')
  1028.                 dir = 1;    /* x / * */
  1029.             else
  1030.                 return;    /* x / x */
  1031.             }
  1032.  
  1033.             /* skip '/' */
  1034.             /* c = dead assign */ get_char (Ep, &curr, dir);
  1035.             /* skip '*' */
  1036.             /* c = dead assign */ get_char (Ep, &curr, dir);
  1037.         }
  1038.         } /* block */
  1039.  
  1040.         nested = FALSE;
  1041.         level = 1;        /* we _are_ inside the comment */
  1042.  
  1043.         /* now look for the first * /-sequence (get_char returns
  1044.            the next char in the specified direction and from within
  1045.            the comment, * / always terminates it */
  1046.         for (;;)
  1047.         {
  1048.         ln = curr.lin;
  1049.         c = get_char (Ep, &curr, dir);
  1050.  
  1051.         if (c == -1)
  1052.             goto not_found;
  1053.  
  1054.         /* Zeilenwechsel ? -> Trenner */
  1055.         if (ln != curr.lin)
  1056.             continue;
  1057.  
  1058.         while (c == '/')
  1059.         {
  1060.             c = get_char (Ep, &curr, dir);
  1061.  
  1062.             if (c == -1)
  1063.             goto not_found;
  1064.  
  1065.             if (c == '*')
  1066.             {
  1067.             level ++;
  1068.             nested = TRUE;
  1069.             }
  1070.         }
  1071.  
  1072.         while (c == '*')
  1073.         {
  1074.             c = get_char (Ep, &curr, dir);
  1075.  
  1076.             if (c == -1)
  1077.             goto not_found;
  1078.  
  1079.             if (c == '/')
  1080.             {
  1081.             level --;
  1082.  
  1083.             if (!level)
  1084.                 goto found;
  1085.             }
  1086.         }
  1087.         }
  1088.  
  1089.         if (nested)
  1090.         warn ("match: nested commend");
  1091.     break; }
  1092.  
  1093.     default:
  1094.         dir = 0;
  1095.     break;
  1096.     }
  1097.  
  1098.     /* if there is no known paren, just return */
  1099.     if (!dir)
  1100.     return;
  1101.  
  1102.     /* we start with level 0. Since we ARE on a paren, this is increased soon */
  1103.     level = 0;
  1104.  
  1105.     for (;;)
  1106.     {
  1107.     c = get_char (Ep, &curr, dir);
  1108.  
  1109.     if (c == -1)
  1110.     {
  1111. not_found:
  1112.         warn ("match: No matching paren");
  1113.         return;
  1114.     }
  1115.  
  1116.     if (c == inc)
  1117.     { /* check for "inc-char" */
  1118.         level ++;
  1119.     } else
  1120.     {
  1121.         if (c == dec)
  1122.         { /* dito */
  1123.         level --;
  1124.  
  1125.         /* if we have reached the start-level, we are through */
  1126.         if (!level)
  1127.             break;
  1128.         }
  1129.     }
  1130.     }
  1131.  
  1132. found:
  1133.     text_sync ();
  1134.  
  1135.     if (curr.lin >= Ep->lines)
  1136.     curr.lin = Ep->lines - 1;
  1137.  
  1138.     Ep->line   = curr.lin;
  1139.     Ep->column = curr.col - dir;    /* undo last oper. in get_char() */
  1140.  
  1141.     text_load ();
  1142.     text_adjust (FALSE);
  1143. } /* do_match */
  1144.  
  1145.  
  1146. void do_ping (void)
  1147. {
  1148.     UWORD num = atoi (av[1]);
  1149.  
  1150.     if (num >= PINGDEPTH)
  1151.     {
  1152.     error ("ping:\n%ld out of range\n(max %ld)", num, PINGDEPTH);
  1153.     return;
  1154.     }
  1155.  
  1156.     marker[num].ep     = Ep;
  1157.     marker[num].column = Ep->column;
  1158.     marker[num].line   = Ep->line;
  1159.  
  1160.     title ("Position marked");
  1161. } /* do_ping */
  1162.  
  1163.  
  1164. void do_pong (void)
  1165. {
  1166.     WORD  num = atoi (av[1]);
  1167.  
  1168.     text_sync ();
  1169.  
  1170.     if (num < 0 || num >= PINGDEPTH || !marker[num].ep)
  1171.     {
  1172.     error ("pong:\nrange error or\nyet nothing marked");
  1173.     return;
  1174.     }
  1175.  
  1176.     text_cursor (1);
  1177.     switch_ed (marker[num].ep);
  1178.     text_cursor (0);
  1179.  
  1180.     if (IntuitionBase->ActiveWindow != Ep->win)
  1181.     {
  1182.     WindowToFront (Ep->win);
  1183.     ActivateWindow (Ep->win);
  1184.     }
  1185.  
  1186.     if ((Ep->line = marker[num].line) >= Ep->lines)
  1187.     {
  1188.     marker[num].line = Ep->line = Ep->lines - 1;
  1189.     }
  1190.  
  1191.     Ep->column = marker[num].column;
  1192.  
  1193.     text_load ();
  1194.     text_adjust (FALSE);
  1195. } /* do_pong */
  1196.  
  1197.  
  1198. int get_pong (int num)
  1199. {
  1200.      if (num < 0 || num >= PINGDEPTH || !marker[num].ep)
  1201.      {
  1202.       return (-1);
  1203.      }
  1204.  
  1205.      if (marker[num].line >= Ep->lines)
  1206.       return (marker[num].line = Ep->lines-1);
  1207.  
  1208.      return (marker[num].line);
  1209. } /* get_pong */
  1210.  
  1211.  
  1212. /*
  1213.  * esc, escimm
  1214.  */
  1215.  
  1216. int Savetopline, Savecolumn, Savetopcolumn;
  1217.  
  1218. void do_recall (void)
  1219. {
  1220.     av[0] = "escimm";
  1221.  
  1222.     /* Copy last Histoline if possible */
  1223.     if (NumHistoLines)
  1224.     av[1] = HistoBuff[NumHistoLines - 1];
  1225.     else
  1226.     av[1] = "";
  1227.  
  1228.     do_esc ();
  1229.  
  1230.     if (NumHistoLines)
  1231.     HistoLine --;
  1232. } /* do_recall */
  1233.  
  1234.  
  1235. void do_esc (void)
  1236. {
  1237.     ED    * ep = Ep;
  1238.     RP    * rp = ep->win->RPort;
  1239.     WORD  y;
  1240.  
  1241.     if (globalflags.Comlinemode)
  1242.     {
  1243.     escapecomlinemode ();
  1244.     return;
  1245.     } else
  1246.     {             /* PATCH_NULL added */
  1247.     esc_partial = Partial;    /* PATCH_NULL added */
  1248.     Partial = NULL;     /* PATCH_NULL added */
  1249.     }
  1250.  
  1251.     text_sync ();
  1252.  
  1253.     if (av[0][3] == 'i')
  1254.     strcpy ((char *)Current, (char *)av[1]);
  1255.     else
  1256.     Current[0] = 0;
  1257.  
  1258.     Clen = strlen ((char *)Current);
  1259.     globalflags.Comlinemode = 1;
  1260.  
  1261.     /* returnoveride (1); */            /* PATCH_NULL [25 Jan 1993] : commented out */
  1262.  
  1263.     Savetopline   = ep->topline;
  1264.     Savecolumn      = ep->column;
  1265.     Savetopcolumn = ep->topcolumn;
  1266.  
  1267.     ep->column = Clen;
  1268.     ep->topcolumn = ep->column - Columns + 1;
  1269.  
  1270.     if (ep->column < Lines)
  1271.     ep->topcolumn = 0;
  1272.     else
  1273.     {
  1274.     ep->topcolumn = Clen - Lines;
  1275.     }
  1276.  
  1277.     ep->topline   = ep->line - Lines + 1;
  1278.  
  1279.     y = ROW (Lines-1);
  1280.     SetAPen (rp, TEXT_BPEN);
  1281.     SetWrMsk (rp, 0xFF);
  1282.     RectFill (rp, COL(0), y, Xpixs, Ypixs);
  1283.  
  1284.     y --;
  1285.     SetAPen (rp, TEXT_FPEN);
  1286.     RectFill (rp, COL(0), y, Xpixs, y);
  1287.  
  1288.     text_displayseg (Lines - 1, 1);
  1289.  
  1290.     text_cursor (1);
  1291.  
  1292.     HistoLine = NumHistoLines;
  1293. } /* do_esc */
  1294.  
  1295.  
  1296. void escapecomlinemode (void)
  1297. {
  1298.     ED     * ep = Ep;
  1299.     RP     * rp = ep->win->RPort;
  1300.     char * ptr;
  1301.  
  1302.     if (esc_partial)
  1303.     {       /* PATCH_NULL P -> esc_p */
  1304.     free(esc_partial);  /* PATCH_NULL P -> esc_p */
  1305.     esc_partial = NULL; /* PATCH_NULL P -> esc_p */
  1306.     }
  1307.  
  1308.     if (globalflags.Comlinemode)
  1309.     {
  1310.     /* Don't add empty lines */
  1311.     if (*Current)
  1312.     {
  1313.         ptr = Current + strlen (Current) -1;
  1314.  
  1315.         while (*ptr == ' ' && ptr != (char *)Current)
  1316.         ptr --;
  1317.  
  1318.         /* Set string-end after last char. Note that this code
  1319.            removes histo-lines with length 1 (single chars) */
  1320.         if (ptr != (char *)Current)
  1321.         ptr ++;
  1322.  
  1323.         *ptr = 0;
  1324.     }
  1325.  
  1326.     /* If we are somewhere above and we didn't change anything,
  1327.        we won't add a new history-line */
  1328.     /* If there is something to add */
  1329.     if (!(HistoLine != NumHistoLines && !strcmp (Current,
  1330.         HistoBuff[HistoLine])) && *Current)
  1331.         {
  1332.         /* Check if buffer is full */
  1333.         if (NumHistoLines == MaxHistoLines)
  1334.         {
  1335.         /* Free oldest line and shift buffer */
  1336.         free (HistoBuff[0]);
  1337.  
  1338.         movmem (HistoBuff + 1, HistoBuff,
  1339.             sizeof (char *) * (MaxHistoLines - 1));
  1340.  
  1341.         /* We have now space for one line */
  1342.         NumHistoLines --;
  1343.         }
  1344.  
  1345.         /* Allocate new line */
  1346.         ptr = malloc (strlen (Current) + 1);
  1347.  
  1348.         /* Copy new line if possible. Note that even if malloc()
  1349.            failed we don't loose information. */
  1350.         if (ptr)
  1351.         {
  1352.         strcpy (ptr, (char *)Current);
  1353.  
  1354.         /* Add line. At this point, NumHistoLines is ALWAYS
  1355.            less than MaxHistoLines ! */
  1356.         HistoBuff[NumHistoLines ++] = ptr;
  1357.         }
  1358.     }
  1359.  
  1360.     globalflags.Comlinemode = 0;
  1361.  
  1362.     /* returnoveride (0); */        /* PATCH_NULL [25 Jan 1993] : commented out */
  1363.  
  1364.     ep->topline   = Savetopline;
  1365.     ep->column    = Savecolumn;
  1366.     ep->topcolumn = Savetopcolumn;
  1367.  
  1368.     text_load ();
  1369.  
  1370.     SetAPen (rp, TEXT_BPEN);
  1371.     SetWrMsk (rp, 0xFF);
  1372.     RectFill (rp, COL(0), ROW(Lines-1)-1, Xpixs, Ypixs);
  1373.  
  1374.     SetAPen (rp, TEXT_FPEN);
  1375.     text_displayseg (Lines - 2, 2);
  1376.     }
  1377. } /* escapecomlinemode */
  1378.  
  1379.  
  1380. void markerkill (ED * ep)
  1381. {
  1382.     WORD  i;
  1383.  
  1384.     for (i = 0; i < PINGDEPTH; ++i)
  1385.     {        /*    remove ping-pong marks    */
  1386.     if (marker[i].ep == ep)
  1387.         marker[i].ep = NULL;
  1388.     }
  1389. } /* markerkill */
  1390.  
  1391.  
  1392. /******************************************************************************
  1393. *****  ENDE cursor.c
  1394. ******************************************************************************/
  1395.